package org.common.utils.net.netty.http.core;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.*;
import org.common.utils.json.JSONTool;
import org.common.utils.net.netty.core.NettyHandler;
import org.common.utils.net.netty.http.intercept.HttpInterceptPool;
import org.common.utils.net.netty.http.exception.HttpNotRouterException;
import org.common.utils.net.netty.http.listener.HttpListenerPool;
import org.common.utils.thread.ThreadTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;

import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;

/**
 * 默认的Http处理器
 * @author zhouzhibing
 * @date 2025/11/14 22:39
 */
@ChannelHandler.Sharable
public class HttpHandler extends NettyHandler {

    private static final Logger log = LoggerFactory.getLogger(HttpHandler.class);
    /**
     * 线程执行器
     */
    private final Executor executor;
    /**
     * 路由池
     */
    private final RouterPool routerPool;
    /**
     * 是否打开异常信息显示
     */
    private boolean openExceptionShow;
    /**
     * 拦截器池
     */
    private final HttpInterceptPool interceptPool;
    /**
     * 监听器池
     */
    private final HttpListenerPool listenerPool;

    /**
     * 创建HttpHandler
     * @param routerPool 路由池
     * @param interceptPool 拦截器池
     * @param listenerPool 监听器池
     * @param executor 线程执行器
     */
    public HttpHandler(RouterPool routerPool, HttpInterceptPool interceptPool, HttpListenerPool listenerPool, ExecutorService executor) {
        this.routerPool = Objects.requireNonNull(routerPool);
        this.interceptPool = Objects.requireNonNull(interceptPool);
        this.listenerPool = Objects.requireNonNull(listenerPool);
        this.executor = Objects.requireNonNull(executor);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.warn("channelActive : {}", ctx.channel());
        listenerPool.channelActive(ctx);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        FullHttpRequest request = (FullHttpRequest) msg;
        if (!interceptPool.channelReadStart(ctx ,  request)) {
            return;
        }

        listenerPool.channelReadStart(ctx , request);
        executor.execute(() -> handlerRequest(ctx , request));
    }

    private void handlerRequest(ChannelHandlerContext ctx, FullHttpRequest request) {
        Object result = null;
        HttpResponseStatus state = null;
        HttpRequest httpRequest = null;

        try {
            // 解析URI和HTTP方法
            URI uri = new URI(request.uri());
            String path = uri.getPath();
            RouteInfo routeInfo = routerPool.getRouteInfo(path);
            if(routeInfo == null) {
                throw new HttpNotRouterException(path);
            }

            httpRequest = new HttpRequest(request , routeInfo);
            if (!interceptPool.handlerRequestBefore(httpRequest)) {
                return;
            }

            listenerPool.handlerRequestBefore(httpRequest);
            result = routeInfo.invoke(httpRequest);
            state = HttpResponseStatus.OK;
            listenerPool.handlerRequestAfter(httpRequest , result);

        } catch (Exception e) {
            log.error("handlerRequest error , request: {}" , request , e);
            state = HttpResponseStatus.INTERNAL_SERVER_ERROR;
            result = openExceptionShow ? ThreadTool.toExceptionString(e) : state.reasonPhrase();
            listenerPool.handlerException(httpRequest , e);
        } finally {
            request.release();
            sendResponse(ctx, state, result);
        }
    }

    // 发送响应工具方法
    private static void sendResponse(ChannelHandlerContext ctx,  HttpResponseStatus status, Object result) {
        String content = null;
        if(status == HttpResponseStatus.OK) {
            content = result == null ? "null" : JSONTool.toJSONString(result);
        } else {
            content = result == null ? "null" : result.toString();
        }

        FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, status, Unpooled.copiedBuffer(content, StandardCharsets.UTF_8));
        HttpHeaders headers = response.headers();

        headers.set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");
        headers.set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
        headers.set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);

        // 支持CORS
        headers.set(HttpHeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
        headers.set(HttpHeaderNames.ACCESS_CONTROL_ALLOW_METHODS, "GET, POST, OPTIONS");
        headers.set(HttpHeaderNames.ACCESS_CONTROL_ALLOW_HEADERS, "Content-Type");

        ctx.writeAndFlush(response);
    }


    private void test(HttpRequest httpRequest) {
        String body = httpRequest.getBody();
        Map<String, String> queryParams = httpRequest.getQueryParams();
        Map<String, String> pathParams = httpRequest.getPathParams();
        Map<String, String> pathParams1 = httpRequest.getPathParams();
        Map<String, String> headers = httpRequest.getHeaders();
        HttpMethod method = httpRequest.getMethod();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("exceptionCaught : {}" , ctx.channel() , cause);
        listenerPool.channelException(ctx , cause);
        ctx.close();
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        log.warn("channelUnregistered : {}", ctx.channel());
        listenerPool.channelUnregistered(ctx);
    }

    public void openExceptionShow() {
        openExceptionShow = true;
    }

    public void closeExceptionShow() {
        openExceptionShow = false;
    }
}
